/************************************************************************
Copyright 2003, 2004, 2005, 2006, 2007, 2008 Grid Technology Research Center,
National Institute of Advanced Industrial Science and Technology.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************/

package jp.aist.gtrc.plus.command.util;

import java.rmi.registry.Registry;
import java.util.Calendar;

import jp.aist.gtrc.plus.reserve.ReserveException;
import jp.aist.gtrc.plus.reserve.ReserveId;
import jp.aist.gtrc.plus.scheduler.util.AppOption;
import jp.aist.gtrc.plus.scheduler.util.HostUtil;
import jp.aist.gtrc.plus.scheduler.util.Option;
import jp.aist.gtrc.plus.scheduler.util.TimeUtil;
import jp.aist.gtrc.plus.scheduler.util.TextUtil;

class PlusCommandOptions extends AppOption {

	//private static final String OPT_RSV_SERVER = "-R";
	protected static final String OPT_TRANSACTION = "-T";
	protected static final String OPT_RSV_START = "-s";
	protected static final String OPT_RSV_END = "-e";
	//static final String OPT_RSV_START2 = "-R";		// PBSPro style
	//static final String OPT_RSV_END2 = "-E";		// PBSPro style
	protected static final String OPT_RSV_DURATION = "-D";
	protected static final String OPT_RSV_NODENUM = "-n";
	protected static final String OPT_RSV_USERS = "-U";
	protected static final String OPT_RSV_ID = "-r";
	protected static final String OPT_OF_OWNER = "-o";
	protected static final String SAMPLE_RSV_ID = ReserveId.RSVID_PREFIX + "123";
	protected static final String OPT_RMI_PORT = "-rp";
	protected static final String ENV_RMI_PORT = "PLUS_RMI_PORT";

	public static final int NO_DURATION = -1;

	protected PlusCommandOptions(String appName) {

		super(appName);
		//addOption(reserveHost());
		addOption(rmiPort());

	}

	/*
	private Option reserveHost() {

		return new Option(OPT_RSV_SERVER, "rsvSrvName",
				"reservation server hostname", PluSUtil.getLocalHostName());

	}
	*/

	public String getReserveServerHost() {

		//return getOptionValue(OPT_RSV_SERVER);
		return HostUtil.getLocalHostName();

	}

	protected Option transaction() {

		return new Option(OPT_TRANSACTION,
			"act as 2-phase, need to use plus_commit/abort");

	}

	protected boolean isTransaction() {

		return isOptionSet(OPT_TRANSACTION);

	}

	protected static final String SUPPORT_TIME_NOTATION
		= "yyyy-MM-DDTHH:mm:ss{+-}zz:zz or [[[[CC]YY]MM]DD]hhmm[.SS]";

	protected Option startTime(boolean isRequired) {

		return new Option(OPT_RSV_START, "startTime",
				"reservation start time, " + SUPPORT_TIME_NOTATION,
				null, isRequired);

	}

	protected Option endTime(boolean isRequired) {

		return new Option(OPT_RSV_END, "endTime",
				"reservation end time (same notaion of startTime)",
				null, isRequired);

	}

	protected Calendar parseTime(String time) {

		return TimeUtil.makeCalendar(time);

	}

	private Calendar getTime(String optKey, String optName) throws ReserveException {

		String s = getOptionValue(optKey);
		if (TextUtil.isValid(s)) {
			Calendar c = parseTime(s);
			if (c != null) {
				return c;
			} else {
				throw new ReserveException("invalid " + optName + ": " + s);
			}
		} else {
			return null;
		}

	}

	protected Calendar getStartTime() throws ReserveException {

		return getTime(OPT_RSV_START, "startTime");

	}

	protected Calendar getEndTime() throws ReserveException {

		return getTime(OPT_RSV_END, "endTime");

	}

	protected Option duration() {

		return new Option(OPT_RSV_DURATION, "duration",
				"reservation duration, [[hh:]mm:]ss", null);

	}

	protected int getDuration() throws ReserveException {

		String d = getOptionValue(OPT_RSV_DURATION);
		if (TextUtil.isEmpty(d))
			return NO_DURATION;

		try {
			return TimeUtil.hhmmssToSec(d);
		} catch (NumberFormatException e) {
			throw new ReserveException(e.getMessage());
		}

	}

	protected Option nodeNum(boolean isRequired) {

		return new Option(OPT_RSV_NODENUM, "nodeNum",
				"number of reserve node", null, isRequired);

	}

	protected int getNodeNum() throws ReserveException {

		String n = getOptionValue(OPT_RSV_NODENUM);
		if (TextUtil.isValid(n)) {
			try {
				return Integer.parseInt(n);
			} catch (NumberFormatException e) {
				throw new ReserveException("invalid node num: " + n);
			}
		} else {
			return 0;
		}

	}

	protected Option users(boolean onlyMe) {

		String userName = (onlyMe) ? PlusReserveCommand.getMyname() : null;
		return new Option(OPT_RSV_USERS, "users",
				"reservation users, userA[,userB,...]", userName);

	}

	private String[] getDefaultUsers() {

		return new String[]{ PlusReserveCommand.getMyname() };

	}

	protected String[] getUsers() {

		String u = getOptionValue(OPT_RSV_USERS);
		if (TextUtil.isEmpty(u)) {
			return getDefaultUsers();
		} else {
			return u.split(",");
		}

	}

	protected Option reserveId(boolean isRequired) {

		return new Option(OPT_RSV_ID, "reserveId",
				"reservation ID (ex: \"" + SAMPLE_RSV_ID + "\")", "", isRequired);
	}

	protected ReserveId getReserveId() throws ReserveException {

		if (isOptionSet(OPT_RSV_ID)) {
			ReserveId rsvId = ReserveId.getInstance(getOptionValue(OPT_RSV_ID));
			if (rsvId != null) {
				return rsvId;
			} else {
				throw new ReserveException("Invalid reserve id, must be "
						+ SAMPLE_RSV_ID + " etc");
			}
		} else {
			return null;
		}

	}

	protected Option owner() {

		return new Option(OPT_OF_OWNER, "owner", "reservation owner", null);

	}

	protected String getOwner() {

		return getOptionValue(OPT_OF_OWNER);

	}

	protected final Option rmiPort() {

		String envPort = System.getenv(ENV_RMI_PORT);
		String defaultPort = TextUtil.isValid(envPort)
			? envPort :  Integer.toString(Registry.REGISTRY_PORT);
		return new Option(OPT_RMI_PORT, "rmiPort",
				"RMI registry port (use "
				+ ENV_RMI_PORT + " env value to set default)", defaultPort);

	}

	public int getRMIPort() throws ReserveException {

		String s = getOptionValue(OPT_RMI_PORT);
		if (TextUtil.isValid(s)) {
			try {
				int port = Integer.parseInt(s);
				return port;
			} catch (NumberFormatException e) {
				if (System.getenv(ENV_RMI_PORT) != null) {
					throw new ReserveException("invalid port num: " + s
							+ ", env value " + ENV_RMI_PORT + " is invalid");
				} else {
					throw new ReserveException("invalid port num: " + s);
				}
			}
		} else {
			return Registry.REGISTRY_PORT;
		}

	}

}
